// version3 在version2的基础上，将收集 依赖/回调函数、触发回调队列 封装为一个Dep类
class Dep{

    static target = null; // 书中写为window.target 这里写为 Dep.target

    constructor(){
        this.subs = []; //订购的主题（订阅者模式），也就是回调函数 队列
    }

    addSub(sub){
        this.subs.push(sub);
    }

    removeSub(sub){
        if(this.subs.length){
            let deleteIndex = this.subs.findIndex(item=>item==sub);
            if(deleteIndex>-1){
                return this.subs.splice(deleteIndex,1);
            }
        }
    }

    // 获取当前 依赖、回调
    depend(){
        if(Dep.target){
            // this.addSub(Dep.target) // 这样写下面的notify报错
            this.addSub({ update: Dep.target})
        }
    }

    //  触发此属性的修改 回调队列 
    notify(val){
        const subs = this.subs.slice(0);
        for(let i=0;i<subs.length;i++){
            subs[i].update(val);
        }
    }
}

function defineReactive(obj={}, key='',val){
    const dep = new Dep();
    Object.defineProperty(
        obj,
        key,
        {
            enumerable: true,
            configurable: true,
            get: function(){

                dep.depend();
                Dep.target = undefined;

                return val;             
            },
            set: function(newVal){
                if(val==newVal){
                    return;
                }                
                val = newVal;

                dep.notify(newVal);
            }
        }
    )
}

const obj = { name:'dwqjdw',age:18 };

Dep.target = function(val){
    console.log('这是 name 属性改变的回调',`修改后为： ${val}`);
}
defineReactive(obj,'name',obj.name);
obj.name; // 收集依赖

Dep.target = function(val){
    console.log('这是 age 属性改变的回调',`修改后为： ${val}`);
}
defineReactive(obj,'age',obj.age);
obj.age; // 收集依赖

obj.name = 'fnewjfnewjkfnewkjnc';  // 只触发name的回调，因为name和age调用了两次函数，有不同的闭包
obj.age = 488;

console.log('==============end============');

